package main

import (
	"context"
	"log"
	"os"
	"os/signal"

	"ruoyi-go-echo-ddd/internal/infrastructure/persistence/config"
	"ruoyi-go-echo-ddd/internal/infrastructure/utils"
	"syscall"
	"time"

	"github.com/duke-git/lancet/v2/slice"
	"github.com/rs/zerolog"

	echoSwagger "github.com/swaggo/echo-swagger"
	_ "ruoyi-go-echo-ddd/docs"
	"ruoyi-go-echo-ddd/internal/domain/model"
)

// @title Echo Swagger API接口文档
// @version 1.0
// @description echo+swagger测试

// @contact.name swagger帮助文档
// @contact.url http://www.swagger.io/support

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization
// @host localhost:8083

// @tag.name 菜单资源管理
// @tag.description 菜单资源管理相关接口

// @tag.name 部门管理
// @tag.description 部门管理相关接口

// @tag.name 角色管理
// @tag.description 角色管理相关接口

// @tag.name 菜单管理
// @tag.description 菜单管理相关接口

// @tag.name 岗位管理
// @tag.description 岗位管理相关接口

// @tag.name 验证码控制器
// @tag.description 验证码相关接口

// @BasePath /
// @schemes http
func main() {
	if err := config.ZeroInit(); err != nil {
		log.Fatalf("zero日志初始化错误===%+v", err)
	}
	logger := zerolog.DefaultContextLogger

	stringSlice := []string{"a", "b", "c", "c", "c"}

	result1 := slice.Contain([]string{"a", "a", "b", "c"}, "a")
	result2 := slice.Contain([]int{1, 2, 3}, 4)

	logger.Info().Msgf("是否包含===%t", result1)
	logger.Info().Msgf("是否包含===%t", result2)

	logger.Info().Msgf("去重===%v", slice.Union(stringSlice))

	roleExcel := &model.SysRole{
		Id:                0,
		MenuCheckStrictly: "",
		DeptCheckStrictly: "",
		RoleStatus:        "",
	}

	logger.Info().Msgf("序列化json===%v", utils.ToJson(roleExcel))

	if err := config.InitGlobalConfig(); err != nil {
		logger.Error().Err(err).Msg("全局配置文件初始化错误")
	}

	_, err := config.NacosClientInit()
	if err != nil {
		logger.Error().Msgf("Nacos Client Init Failed===%+v", err)
	}

	minioClient, err := config.InitMinioClient()
	if err != nil {
		logger.Error().Msgf("Minio Client Init Failed===%+v", err)
	}

	pgDb, err := config.InitGormPostgresConn()
	if err != nil || pgDb.DB == nil {
		logger.Fatal().Err(err).Msg("Gorm Postgresql Init Failed===")
	}
	config.GlobalPgDb = pgDb.DB

	logger.Info().Msgf("Gorm Postgresql Connection init successful, %v", pgDb.PrepareStmt)

	mysqlDB, err := config.InitGormMysqlConn()
	if err != nil || mysqlDB.DB == nil {
		logger.Fatal().Msgf("Gorm Mysql Init Failed===%+v", err)
	}

	config.GlobalMysqlDb = mysqlDB.DB

	logger.Info().Msgf("Gorm Mysql Connection init successful, %v", mysqlDB.PrepareStmt)

	redisClient, err := config.InitRedisClient()
	if err != nil || redisClient == nil {
		logger.Fatal().Msgf("Redis Client Init Failed===%+v", err)
	}

	config.GlobalRedisClient = redisClient

	redisStore, err := utils.NewRedisStore(redisClient,
		config.CacheConfig.Captcha.Prefix,
		config.CacheConfig.Captcha.Expiration)

	if err != nil {
		logger.Error().Err(err).Msg("redis client store init error")
	}

	/*menuResourcesDao := dao.NewMenuResourcesDaoImpl(pgDb)
	  menuResourcesService := service.NewSysMenuResourcesService(menuResourcesDao)
	  menuResourcesApplication := application.NewSysMenuResourcesApplication(menuResourcesService)
	  menuResourcesHandler := handler.NewSysMenuResourcesHandler(menuResourcesApplication)

	  roleMenuDao := dao.NewSysRoleMenuDaoImpl(pgDb)
	  roleDeptDao := dao.NewSysRoleDeptDaoImpl(pgDb)

	  roleDao := dao.NewSysRoleDaoImpl(pgDb, roleMenuDao, roleDeptDao)
	  deptDao := dao.NewSysDeptDaoImpl(pgDb, roleDao)

	  deptService := service.NewSysDeptService(deptDao)
	  tokenService := service.NewTokenService(redisClient)
	  deptApplication := application.NewSysDeptApplication(deptService)
	  tokenApplication := application.NewTokenApplication(tokenService)
	  sysDeptHandler := handler.NewDeptHandler(deptApplication, tokenApplication)

	  appEcho, err := http.NewEchoRouter(menuResourcesHandler, sysDeptHandler)
	  if err != nil {
	  	panic(err)
	  }*/

	appEcho, clean, err := WireApp(pgDb, mysqlDB, minioClient, redisClient, redisStore)

	// 引入swagger
	// 请求处理器增加注释后，使用swag init wire_gen.go main.go --parseDependency --parseInternal重新生成文档
	appEcho.GET("/swagger/*", echoSwagger.WrapHandler)
	//appEcho.Static("/swagger", "docs")

	if err != nil {
		panic(err)
	}
	defer clean()
	port := config.ServerConfig.Port

	// 修复点：在独立协程启动服务器
	serverErr := make(chan error)
	go func() {
		// echoRequestRouter(app)
		logger.Info().Msgf("echo服务启动端口=====:%s", port)
		serverErr <- appEcho.Start(":" + port)
	}()

	// 修复点：信号处理与优雅关闭
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

	select {
	case err = <-serverErr:
		if utils.IsAddrInUseErr(err) {
			logger.Fatal().Err(err).Msgf("echo启动失败,端口号===%s已被占用或者已启动", port)
		}
		logger.Fatal().Err(err).Msg("服务意外退出")
	case <-quit:
		logger.Info().Msg("收到关闭信号")

		// 停止所有服务
		stopCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()

		if err = appEcho.Shutdown(stopCtx); err != nil {
			logger.Error().Err(err).Msg("服务关闭失败")
		}
		logger.Info().Msg("服务已优雅退出")
	}
	// go run -tags=goexperiment.jsonv2 wire_gen.go main.go
}
